package com.atguigu.junit.auto;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Author: shenhao
 * @CreatTime: 2024/10/13 21:30
 * @Version: 1.0
 * 自动测试业务类,使用了反射的知识
 */
@Slf4j
public class AutoTestClient {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<?> aClass = Class.forName("com.atguigu.junit.auto.CalcHelpDemo");
//        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
//        declaredConstructor.setAccessible(true);
//        CalcHelpDemo calcHelpDemo = (CalcHelpDemo)declaredConstructor.newInstance();
        CalcHelpDemo calcHelpDemo = (CalcHelpDemo) aClass.newInstance();
        int para1 = 10;
        int para2 = 0;

        Method[] methods = calcHelpDemo.getClass().getMethods();
        //原子性Integer
        AtomicInteger bugCount = new AtomicInteger(0);
        //要写入的文件路径,如果文件不存在,会创建该文件
        String filePath = "BugReport"+(DateUtil.format(new Date(),"yyyyMMddHHmmss"))+".txt";

        for (int i = 0; i < methods.length; i++) {
            // isAnnotationPresent()如果此元素 上存在 指定类型的注释，则返回 true，否则返回 false。此方法主要是为了方便访问标记注释而设计的。
            if (methods[i].isAnnotationPresent(AtguiguTest.class)){
                int[] value = methods[i].getAnnotation(AtguiguTest.class).value();
                log.info("注解的值的长度为{},应为2",value.length);
                int result = value[0];
                int result2 = value[1];
                try {
                    //methods[i].invoke(calcHelpDemo,para1,para2);
                    methods[i].invoke(calcHelpDemo,result,result2);
                }  catch (Exception e) {
                    bugCount.incrementAndGet();
                    // e.getCause()返回此 throwable 的原因，或者 null 如果原因不存在或未知。（原因是导致此 throwable 被抛出的 throwable。
                    log.info("异常名称:{},异常原因:{}",e.getCause().getClass().getSimpleName(),e.getCause().getMessage());
                    FileUtil.writeString(methods[i].getName()+"\t"+"出现了异常"+"\n",filePath,"UTF-8");
                    FileUtil.appendString("异常名称:"+e.getCause().getClass().getSimpleName()+"\n",filePath,"UTF-8");
                    FileUtil.appendString("异常原因:"+e.getCause().getMessage()+"\n",filePath,"UTF-8");
                } finally {
                    FileUtil.appendString("异常数:"+bugCount.get()+"\n",filePath,"UTF-8");
                }
            }
        }
    }
}


/**
 * 在Hutool工具包中，使用FileUtil类进行文件操作时，通常不需要显式地“关闭”文件。
 * 这是因为Hutool在内部处理文件I/O时，已经考虑了资源的自动管理和释放。
 *
 * 具体来说，当你使用FileUtil的静态方法（如writeString、appendString、readUtf8String等）时，
 * 这些方法会在执行完毕后自动关闭与文件相关的流和资源。因此，你不需要（也不能）
 * 调用类似于close这样的方法来关闭文件。
 *
 * 这是因为这些静态方法通常使用Java的try-with-resources语句或其他类似的机制来确保资源在
 * 不再需要时得到释放。try-with-resources是Java 7及更高版本中引入的一个特性，
 * 它允许你在try语句块结束时自动关闭实现了AutoCloseable或Closeable接口的资源。
 *
 * 所以，当你使用Hutool的FileUtil类进行文件操作时，你可以放心地编写代码，
 * 而无需担心资源泄露或忘记关闭文件的问题。Hutool已经为你处理了这些细节。
 */
